#include "MyWidget.h"

static const QString ACCESS_KEY = "<YOUR AK>";
static const QString SECRET_KEY = "<YOUR SK>";
static const QString REGION = "<YOUR URL REGION>";
static const QString TTS_REQUEST_URL = "<YOUR TTS_REQUEST_URL>";
static const QString TOKEN_REQUEST_URL = "<YOUR REQUEST TOKEN>";
static const QString LANGUAGE_SPEAKER_DOMAIN = "chinese_xiaoyan_common";

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
    resize(800, 500);
    m_layout = new QVBoxLayout;
    m_widget = new QWidget(this);
    m_player = new QMediaPlayer(this);
}

// 创建语音合成应用及可视化界面
void MyWidget::TextToSpeech()
{
    m_playIconPath = QApplication::applicationDirPath() + "/asserts/play.png";
    m_pauseIconPath = QApplication::applicationDirPath() + "/asserts/pause.png";
    if (m_textInputEdit == nullptr) {
        m_textInputEdit = new QTextEdit(this);
        m_textInputEdit->setPlaceholderText("Enter Text (no more than 500 characters)");
        m_textInputEdit->setFixedHeight(300);
        m_textInputEdit->setFixedWidth(780);
    }
    m_layout->addWidget(m_textInputEdit); 

    QPushButton *convertButton = new QPushButton("Click to Convert", this);
    m_layout->addWidget(convertButton);

    m_playButton = new QPushButton(this);
    m_playButton->setFlat(true);
    m_playButton->setIcon(QPixmap(m_pauseIconPath));
    m_playButton->setIconSize(QSize(100, 100));

    m_layout->addWidget(m_playButton);
    m_layout->setAlignment(Qt::AlignCenter);
    m_widget->setLayout(m_layout);
    m_textInputEdit->show();
    m_textInputEdit->setFocus();

    connect(convertButton, &QPushButton::clicked, this, &MyWidget::ShowTextToSpeechResult);
    connect(m_player, &QMediaPlayer::stateChanged, this, &MyWidget::OnPlayerStateChanged);
    connect(m_playButton, &QPushButton::clicked, this, &MyWidget::OnPlayButtonClicked);
    return;
}

// 解码base64格式的音频数据并生成音频文件播放
void MyWidget::ShowTextToSpeechResult()
{
    // 获取语音合成API返回的响应Json数据
    QJsonDocument textToSpeechData = GetTextToSpeechResult();
    if (textToSpeechData.isNull()) {
        return;
    }
    QString encodedData = textToSpeechData.object()["result"].toObject()["data"].toString();
    QByteArray encodedDataBytes = encodedData.toLatin1();
    QByteArray decodedDataBytes = QByteArray::fromBase64(encodedDataBytes);
    
    // 生成.wav音频文件
    m_audioPath = QApplication::applicationDirPath() + "/asserts/audio.wav"; 
    QFile file(m_audioPath);
    if (file.exists()) {
        file.remove();
    }
    if (!file.open(QIODevice::WriteOnly)) {
        qDebug() << "Failed to open file for writing";
        return;
    }
    file.write(decodedDataBytes);
    file.close();
    m_audioSetFlag = true;
    return;
}

// 生成语音合成API调用的http请求并发送，获取返回的响应数据
QJsonDocument MyWidget::GetTextToSpeechResult()
{
    QNetworkAccessManager manager;
    QNetworkRequest request;
    request.setUrl(QUrl(TTS_REQUEST_URL));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    m_token = GetToken();
    request.setRawHeader("X-Auth-Token", m_token);
    QJsonObject requestBody;
    QJsonObject configSpeech;
    QString inputText = m_textInputEdit->toPlainText();
    requestBody["text"] = inputText;
    configSpeech["property"] = LANGUAGE_SPEAKER_DOMAIN;
    requestBody["config"] = configSpeech;
    QJsonDocument jsonDocument(requestBody);
    QByteArray requestData = jsonDocument.toJson();
    QNetworkReply *reply = manager.post(request, requestData);
    QEventLoop loop;
    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    loop.exec();
    QJsonDocument jsonResponse;
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray responseData = reply->readAll();
        jsonResponse = QJsonDocument::fromJson(responseData);
    } else {
        qDebug() << "Error:" << reply->errorString();
    }
    reply->deleteLater();
    return jsonResponse;
}

// 音频播放/暂停控制
void MyWidget::OnPlayButtonClicked()
{
    if (m_audioSetFlag == true) {
        m_player->setMedia(QMediaContent());
        m_player->setMedia(QUrl::fromLocalFile(m_audioPath));
        m_player->setVolume(60);
        m_audioSetFlag = false;
    }  
    if (m_player->state() == QMediaPlayer::PlayingState) {
        m_player->pause();
    } else {
        m_player->play();     
    }
    return;
}

void MyWidget::OnPlayerStateChanged(QMediaPlayer::State state)
{
    if (state == QMediaPlayer::PlayingState) {
        m_playButton->setIcon(QPixmap(m_playIconPath));
    } else {
        m_playButton->setIcon(QPixmap(m_pauseIconPath));
    }
    return;
}

// 填充http请求
static QJsonObject FillRequestBody()
{
    QJsonObject requestBody;
    QJsonObject authObject;
    QJsonObject identityObject;
    QJsonArray methodsArray;
    methodsArray.append("hw_ak_sk");
    QJsonObject akSkObject;
    QJsonObject accessObject;
    accessObject["key"] = ACCESS_KEY;
    QJsonObject secretObject;
    secretObject["key"] = SECRET_KEY;
    akSkObject["access"] = accessObject;
    akSkObject["secret"] = secretObject;
    identityObject["hw_ak_sk"] = akSkObject;
    identityObject["methods"] = methodsArray;
    authObject["identity"] = identityObject;
    QJsonObject scopeObject;
    QJsonObject projectObject;
    projectObject["name"] = REGION;
    scopeObject["project"] = projectObject;
    authObject["scope"] = scopeObject;
    requestBody["auth"] = authObject;
    return requestBody;
}

// 获取用户token
QByteArray MyWidget::GetToken()
{
    QNetworkAccessManager manager;
    QNetworkRequest request;
    request.setUrl(QUrl(TOKEN_REQUEST_URL));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    QJsonObject requestBody = FillRequestBody();
    QJsonDocument jsonDocument(requestBody);
    QByteArray requestData = jsonDocument.toJson();
    QNetworkReply *reply = manager.post(request, requestData);
    QEventLoop loop;
    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    loop.exec();
    QJsonDocument jsonResponse;
    if (reply->error() == QNetworkReply::NoError) {
        QVariant token = reply->rawHeader("X-Subject-Token");
        m_token = token.toByteArray();
    } else {
        qDebug() << "Error:" << reply->errorString();
    }
    reply->deleteLater();
    return m_token;
}
